package Offer2019;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

public class ABADemo {

    static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);
    //static方便直接使用
    static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100, 1);

    //ABA问题
    public static void main(String[] args) {
        //new Thread(() -> {
        //    atomicReference.compareAndSet(100, 101);
        //    atomicReference.compareAndSet(101, 100);
        //}, "t1").start();
        //
        //
        //new Thread(() -> {
        //    try {
        //        //暂停1秒，保证t1已经完成了一次ABA操作
        //        TimeUnit.SECONDS.sleep(1);
        //    } catch (InterruptedException e) {
        //        e.printStackTrace();
        //    }
        //    System.out.println(atomicReference.compareAndSet(100, 2020)+"\t"+atomicReference.get());
        //}, "t2").start();


        //ABA问题的解决
        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();//版本号
            System.out.println(Thread.currentThread().getName() + "\t第一次版本号：" + stamp);
            try {
                //确保t4线程拿到初始版本号
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            atomicStampedReference.compareAndSet(100, 101, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
            System.out.println(Thread.currentThread().getName() + "\t第二次版本号：" + atomicStampedReference.getStamp());
            atomicStampedReference.compareAndSet(101, 100, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
            System.out.println(Thread.currentThread().getName() + "\t第三次版本号：" + atomicStampedReference.getStamp());

        }, "t3").start();

        //ABA问题的解决
        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + "\t第一次版本号：" + stamp);
            try {
                //确保t3线程完成ABA操作
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            atomicStampedReference.compareAndSet(100, 2020, stamp, atomicStampedReference.getStamp() + 1);
            System.out.println(Thread.currentThread().getName() + "\t第二次版本号：" + atomicStampedReference.getStamp() + "\t当前值为：" + atomicStampedReference.getReference());
        }, "t4").start();
    }
}
